﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Web.Mvc;

namespace Intercom.Net
{
    public static class IntercomExtension
    {
        public static IHtmlString IntercomTracking (this HtmlHelper htmlHelper, TrackingData tracking)
        {
            return new HtmlString(tracking.GenerateIntercomTrackingCode());
        }

    }

    public class TrackingData
    {
        /// <summary>
        /// Gets or sets the intercom app id.
        /// </summary>
        /// <value>
        /// Provide your intercom app id.
        /// </value>
        public string IntercomAppId { get; set; }

        /// <summary>
        /// Gets or sets the intercom secret key.
        /// </summary>
        /// <value>
        /// The intercom secret key if you wish to track data in secure mode
        /// </value>
        public string IntercomSecretKey { get; set; }

        /// <summary>
        /// Gets or sets the email address.
        /// </summary>
        /// <value>
        /// The email address of your customer you are tracking
        /// </value>
        public string EmailAddress { get; set; }

        /// <summary>
        /// Gets or sets the signup date.
        /// </summary>
        /// <value>
        /// The signup date, Converted to Unix time stamp. Use your own converter or call the DateTimeToUnixTimestamp method
        /// </value>
        public long SignupDate { get; set; }

        /// <summary>
        /// Gets or sets the user id.
        /// </summary>
        /// <value>
        /// Optional Parameter. Provide a unique identifier for the user from your system. 
        /// </value>
        public string UserId { get; set; }

        /// <summary>
        /// Gets or sets the name of the customer.
        /// </summary>
        /// <value>
        /// The full name of the customer.
        /// </value>
        public string CustomerName { get; set; }

        /// <summary>
        /// Gets or sets the custom data.
        /// </summary>
        /// <value>
        /// Provide a name value pair collection of the the custom data you wish to track
        /// </value>
        public IEnumerable<KeyValuePair<string, string>> CustomData { get; set; }

        internal string GenerateIntercomTrackingCode()
        {
            if (string.IsNullOrEmpty(IntercomAppId))
            {
                throw new InvalidOperationException("Intercom AppId property must be set.");
            }

            var output = new StringBuilder();

            output.Append("<!-- Intercom IO Tracking Code Start --> \n\n");
            output.Append("<script id=\"IntercomSettingsScriptTag\"> \n");
            output.Append("var intercomSettings = {\n");
            output.AppendFormat("app_id: '{0}',\n", IntercomAppId);
            output.AppendFormat("email: '{0}',\n", EmailAddress);
            output.AppendFormat("user_id: '{0}',\n", UserId);
            output.AppendFormat("name: '{0}',\n", CustomerName);
            output.AppendFormat("created_at: {0},\n", SignupDate);

            if (!string.IsNullOrEmpty(IntercomSecretKey))
            {
                output.AppendFormat("user_hash: '{0}'\n", GetHash());
            }

            if (CustomData != null && CustomData.Count() > 0)
            {
                output.Append(",custom_data: {\n");

                // Build Custom data
                foreach (var customDataItem in CustomData)
                {
                    output.AppendFormat("'{0}': '{1}',\n", customDataItem.Key, customDataItem.Value);
                }

                output.Append("}\n");
            }

            output.Append("};\n</script>\n");

            output.Append("<script>\n" +
                "(function () {\n" +
                "function async_load() {\n" +
                "var s = document.createElement('script');\n" +
                "s.type = 'text/javascript'; s.async = true;\n" +
                "s.src = 'https://api.intercom.io/api/js/library.js';\n" +
                "var x = document.getElementsByTagName('script')[0];\n" +
                "x.parentNode.insertBefore(s, x);\n" +
                "}\n" +
                "if (window.attachEvent) {\n" +
                "window.attachEvent('onload', async_load);\n" +
                "} else {\n" +
                "window.addEventListener('load', async_load, false);\n" +
                "}\n" +
                "})();\n" +
                "</script>\n\n"
                );


            output.Append("<!-- Intercom IO tracking Code End -->");

            return output.ToString();

        }

        private string GetHash()
        {
            string encode = IntercomSecretKey + UserId;
            var encoding = new ASCIIEncoding();

            byte[] msgBytes = encoding.GetBytes(encode);

            var sha1Hash = new SHA1Managed();
            byte[] hashValue = sha1Hash.ComputeHash(msgBytes);

            return hashValue.Aggregate("", (current, b) => current + String.Format("{0:x2}", b));
        }

        public static long DateTimeToUnixTimestamp(DateTime dateTime)
        {
            var difference = dateTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            return (long)difference.TotalSeconds;
        }
    }
}
